/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package agen.optimalidad;

import java.util.Arrays;

/**
 * En esta clase se agrupan todos los metodos relacionados con la determinación
 * de optimalida de los individuos.
 * @author juan
 */
public class Optimo {
    /* Array que almacena la mejor aptitud por generacion
     * cada 100 generaciones se redimenciona con 100 eltos más.
     * Esto espara evitar perdidas de tiempo en manejo de memoria.
     */
    public static double[] mejorAptitudXGen = new double[100];
    private static double[] diferencialAptitudXGen = new double[100];
    private static int generacion = 0;
    /*definición de metodos de corte*/
    public static final int OPTIMO_ESTADISTICO = 0;
    public static final int OPTIMO_TOPE_TEHORICO = 1;
    private static int metodoCorte = 0;

    public static void setMedotoCorte(int medotoCorte) {
        Optimo.metodoCorte = medotoCorte;
    }
    public static int getMedotoCorte() {
        return metodoCorte;
    }
    /* indica cuantas generacoines deben pasar sin cambios significativos para
     * devolver un optimo con el metodo estadistico.
     */
    public static int generacionesCorteOptimo = 150;
    /**
     * Recorre todo el array en busca de un individuo que cumpla las condiciones
     * de optimalidad.
     * @param aptitudes
     * @return
     */

    public static int encontrarOptimo(double[] aptitudes) {

        return -1;
    }

    /**
     * Comrueba la optimalidad del primer individuo unicamente, asumiendo
     * que es el mejor.
     * @param aptitudes
     * @param orden
     * @return
     */

    public static int encontrarOptimo(double[] aptitudes, int[] aptitudesOrdenadas) {
		ampliarArrays();
        mejorAptitudXGen[generacion] = aptitudes[0];
        switch (metodoCorte) {
            case OPTIMO_ESTADISTICO:
                if (optimoEstadistico()) {
                    return 0;
                }
                break;
            case OPTIMO_TOPE_TEHORICO:
                System.out.println("OPTIMO_TOPE_TEHORICO no implemetado");
                break;
            default: System.out.println("No se especificó un metodo apropiado");
        }
        generacion++; /*importante incrementar despues de realizar las demás operaciones*/
        return -1;
    }
	private static void ampliarArrays(){
		if (generacion > 0 && generacion % 100 == 0){
			mejorAptitudXGen = Arrays.copyOf(mejorAptitudXGen,
                    mejorAptitudXGen.length + 100);
			diferencialAptitudXGen = Arrays.copyOf(diferencialAptitudXGen,
                    diferencialAptitudXGen.length + 100);
		}
	}
    /**
     * Trata de determinar la optimalidad mediante un analisis de la mejoría
     * en la mejor aptitud de generación en generación. La idea es que si
     * despues de un cierto numero de iteraciones la mejor aptitud cambia
     * muy poco estaríamos en la vecindad del optimo.
     * Esto presenta el riesgo de caer en optimos locales. Resulta util aumentar
     * la probabilidad de mutación por si acaso.
     *
     */

    private static boolean optimoEstadistico() {
        if (generacion > 0 ) {
            diferencialAptitudXGen[generacion - 1] =
                    mejorAptitudXGen[generacion] - mejorAptitudXGen[generacion - 1];
        }
        if (generacion > generacionesCorteOptimo) {
            boolean cortar = true;
            for (int i = generacion - generacionesCorteOptimo; i < generacion ; i++) {
                /*si no hubo mejoria en las ultimas generacionesCorteOptimo
                 * generaciones cortar.
                 */
                if (diferencialAptitudXGen[i] != 0) {
                    cortar = false;
                    break;
                }
            }
            return cortar;
        } else {
            return false;
        }
    }
}
